From: Wei Chen Date: Wed, 5 Apr 2017 09:09:06 +0000 (+0800) Subject: xen/arm: Avoid setting/clearing HCR_RW at every context switch X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~2346 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=24aff0561163988ec1372fa571105fd13735cd67;p=xen.git xen/arm: Avoid setting/clearing HCR_RW at every context switch The HCR_EL2 flags for 64-bit and 32-bit domains are different. But when we initialized the HCR_EL2 for vcpu0 of Dom0 and all vcpus of DomU in vcpu_initialise, we didn't know the domain's address size information. We had to use compatible flags to initialize HCR_EL2, and set HCR_RW for 64-bit domain or clear HCR_RW for 32-bit domain at every context switch. But, after we added the HCR_EL2 to vcpu's context, this behaviour seems a little fussy. We can update the HCR_RW bit in vcpu's context as soon as we get the domain's address size to avoid setting/clearing HCR_RW at every context switch. Signed-off-by: Wei Chen Acked-by: Julien Grall Reviewed-by: Stefano Stabellini --- diff --git a/xen/arch/arm/arm64/domctl.c b/xen/arch/arm/arm64/domctl.c index 44e1e7bb8c..ab8781fb91 100644 --- a/xen/arch/arm/arm64/domctl.c +++ b/xen/arch/arm/arm64/domctl.c @@ -14,6 +14,8 @@ static long switch_mode(struct domain *d, enum domain_type type) { + struct vcpu *v; + if ( d == NULL ) return -EINVAL; if ( d->tot_pages != 0 ) @@ -23,6 +25,10 @@ static long switch_mode(struct domain *d, enum domain_type type) d->arch.type = type; + if ( is_64bit_domain(d) ) + for_each_vcpu(d, v) + vcpu_switch_to_aarch64_mode(v); + return 0; } diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 5d18bb0933..69c28544ca 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -537,6 +537,11 @@ void vcpu_destroy(struct vcpu *v) free_xenheap_pages(v->arch.stack, STACK_ORDER); } +void vcpu_switch_to_aarch64_mode(struct vcpu *v) +{ + v->arch.hcr_el2 |= HCR_RW; +} + int arch_domain_create(struct domain *d, unsigned int domcr_flags, struct xen_arch_domainconfig *config) { diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index de59e5fd0e..3abacc0d80 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -2148,6 +2148,10 @@ int construct_dom0(struct domain *d) return -EINVAL; } d->arch.type = kinfo.type; + + if ( is_64bit_domain(d) ) + vcpu_switch_to_aarch64_mode(v); + #endif allocate_memory(d, &kinfo); @@ -2240,6 +2244,9 @@ int construct_dom0(struct domain *d) printk("Failed to allocate dom0 vcpu %d on pcpu %d\n", i, cpu); break; } + + if ( is_64bit_domain(d) ) + vcpu_switch_to_aarch64_mode(d->vcpu[i]); } return 0; diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 83c4b7db95..34d57760d7 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -137,11 +137,6 @@ void p2m_restore_state(struct vcpu *n) WRITE_SYSREG64(p2m->vttbr, VTTBR_EL2); isb(); - if ( is_32bit_domain(n->domain) ) - n->arch.hcr_el2 &= ~HCR_RW; - else - n->arch.hcr_el2 |= HCR_RW; - WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1); isb(); diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 7b1dacce1f..68185e2ebd 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -268,6 +268,7 @@ struct arch_vcpu void vcpu_show_execution_state(struct vcpu *); void vcpu_show_registers(const struct vcpu *); +void vcpu_switch_to_aarch64_mode(struct vcpu *); unsigned int domain_max_vcpus(const struct domain *);